package com.sample.camerax.analyzer

import android.graphics.ImageFormat
import android.util.Log
import androidx.camera.core.ImageAnalysis
import androidx.camera.core.ImageProxy
import com.google.zxing.*
import com.google.zxing.common.HybridBinarizer
import com.loyal.camerax.utils.ImageUtil
import java.nio.ByteBuffer

private const val TAG = "QrCodeAnalyzer"

class QrCodeAnalyzer() : ImageAnalysis.Analyzer {
    private val reader: MultiFormatReader = MultiFormatReader()
    private var callback: QrCodeParseCallback? = null
    private var path: String? = null

    constructor(callback: QrCodeParseCallback, path: String) : this() {
        this.callback = callback
        this.path = path
    }

    init {
        val map = mapOf<DecodeHintType, Collection<BarcodeFormat>>(
            Pair(
                DecodeHintType.POSSIBLE_FORMATS, arrayListOf(
                    BarcodeFormat.QR_CODE, BarcodeFormat.CODE_39,
                    BarcodeFormat.CODE_128,
                    BarcodeFormat.AZTEC,
                    BarcodeFormat.CODABAR,
                    BarcodeFormat.CODE_93,
                    BarcodeFormat.DATA_MATRIX,
                    BarcodeFormat.EAN_8,
                    BarcodeFormat.EAN_13,
                    BarcodeFormat.ITF,
                    BarcodeFormat.MAXICODE,
                    BarcodeFormat.PDF_417,
                    BarcodeFormat.RSS_14,
                    BarcodeFormat.RSS_EXPANDED,
                    BarcodeFormat.UPC_A,
                    BarcodeFormat.UPC_E,
                    BarcodeFormat.UPC_EAN_EXTENSION
                )
            )
        )
        reader.setHints(map)
    }

    override fun analyze(image: ImageProxy) {
        if (ImageFormat.YUV_420_888 != image.format) {
            Log.e(TAG, "expect YUV_420_888, now = ${image.format}")
            return
        }
        val buffer = image.planes[0].buffer
        val data = buffer.toByteArray()
        val height = image.height
        val width = image.width

        //TODO 调整crop的矩形区域，目前是全屏（全屏有更好的识别体验，但是在部分手机上可能OOM）
        val source = PlanarYUVLuminanceSource(data, width, height, 0, 0, width, height, false)
        val bitmap = BinaryBitmap(HybridBinarizer(source))
        val success = ImageUtil.saveImageByteArray(data, path, 0f)
        if (success) {
            callback?.success("")
        }
        try {
            val result = reader.decode(bitmap)
            callback?.success(result?.text)
        } catch (e: Exception) {
            callback?.error(e)
        }
        image.close()
    }

    private fun ByteBuffer.toByteArray(): ByteArray {
        rewind()    // Rewind the buffer to zero
        val data = ByteArray(remaining())
        get(data)   // Copy the buffer into a byte array
        return data // Return the byte array
    }

    interface QrCodeParseCallback {
        fun success(text: String?)
        fun error(e: Exception)
    }
}